package top.cardone.context.util;

import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
import top.cardone.context.ApplicationContextHolder;
import top.cardone.core.util.func.Func1;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by cardone-home-001 on 2016/4/20.
 */
public class MapUtils extends org.apache.commons.collections.MapUtils {
    /**
     * 转换集合
     *
     * @param map         原集合
     * @param configTable 配置
     * @param <V>         类型
     * @return 新集合
     */
    public static <V> Map<String, V> newHashMap(Map<String, V> map, Table<String, String, String> configTable) {
        if (isEmpty(map) || (configTable == null) || configTable.isEmpty()) {
            return map;
        }

        HashMap<String, V> newMap = Maps.newHashMap();

        for (String rowKey : configTable.rowKeySet()) {
            if (!map.containsKey(rowKey)) {
                continue;
            }

            String newKey = StringUtils.defaultIfBlank(configTable.get(rowKey, "newName"), rowKey);

            String funcBeanIds = StringUtils.defaultString(configTable.get(rowKey, "funcBeanIds"), configTable.get(rowKey, "funcBeanId"));

            if (StringUtils.isBlank(funcBeanIds)) {
                newMap.put(newKey, map.get(rowKey));

                continue;
            }

            Object newValue = map.get(rowKey);

            String[] funcBeanIdArray = StringUtils.split(funcBeanIds);

            for (String funcBeanId : funcBeanIdArray) {
                newValue = ApplicationContextHolder.getBean(Func1.class, funcBeanId).func(newValue);
            }

            newMap.put(newKey, (V) newValue);
        }

        return newMap;
    }

    public static Map toMap(Object obj, String objectKey) {
        return toMap(obj, "objs", objectKey);
    }

    public static Map toMap(Object obj, String objectsKey, String objectKey) {
        Map<Object, Object> newMap;

        if (obj == null) {
            newMap = Maps.newHashMap();
        } else if (obj instanceof Map) {
            newMap = (Map) obj;
        } else if ((obj instanceof Iterable) || ObjectUtils.isArray(obj)) {
            newMap = Maps.newHashMap();

            newMap.put(objectsKey, obj);
        } else {
            newMap = Maps.newHashMap();

            if (obj.getClass().isPrimitive() ||
                    obj.getClass().equals(String.class) ||
                    obj.getClass().equals(Integer.class) ||
                    obj.getClass().equals(Byte.class) ||
                    obj.getClass().equals(Long.class) ||
                    obj.getClass().equals(Double.class) ||
                    obj.getClass().equals(Float.class) ||
                    obj.getClass().equals(Character.class) ||
                    obj.getClass().equals(Short.class) ||
                    obj.getClass().equals(BigDecimal.class) ||
                    obj.getClass().equals(BigInteger.class) ||
                    obj.getClass().equals(Boolean.class) ||
                    obj.getClass().equals(Date.class)) {
                newMap.put(org.apache.commons.lang3.StringUtils.defaultString(objectKey, "obj"), obj);

                return newMap;
            }

            ReflectionUtils.doWithFields(obj.getClass(), field -> {
                Object value = FieldUtils.readField(field, obj, true);

                newMap.put(field.getName(), value);
            }, ReflectionUtils.COPYABLE_FIELDS);
        }

        return newMap;
    }
}
